package com.jx.driving.message;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import org.apache.commons.lang3.StringUtils;

/**
 * 消息与id的映射关系
 * 
 * @author shenliuyang
 *
 *         2016年8月4日下午5:01:22
 */
public class MessageIdMapper {

	public static final MessageIdMapper instance = new MessageIdMapper();

	private Map<Integer, Class<?>> id2Class = new ConcurrentHashMap<>();

	private Map<Class<?>, Integer> class2Id = new ConcurrentHashMap<>();

	/**
	 * 根据id获取消息类型
	 */
	public Class<?> getClass(Integer id) {
		Class<?> clazz = id2Class.get(id);
		if (clazz != null) {
			return clazz;
		}
		String hexadecimal = Integer.toHexString(id).toUpperCase();
		int len = 4 - hexadecimal.length();
		StringBuffer sb = new StringBuffer(4);
		for (int i = 0; i < len; i++) {
			sb.append("0");
		}
		sb.append(hexadecimal);
		hexadecimal = sb.toString();
		String requestPackage = "com.jx.driving.request.Terminal0x" + hexadecimal + "Request";
		String responsePackage = "com.jx.driving.response.Terminal0x" + hexadecimal + "Response";
		try {
			clazz = Class.forName(requestPackage);
		} catch (ClassNotFoundException e) {
			try {
				clazz = Class.forName(responsePackage);
			} catch (ClassNotFoundException ex) {
				throw new RuntimeException("request or response class not found by id " + hexadecimal, ex);
			}
		}
		id2Class.put(id, clazz);
		class2Id.put(clazz, id);
		return clazz;
	}

	/**
	 * 根据消息类型获取id
	 */
	public Integer getId(Class<?> clazz) {
		Integer id = class2Id.get(clazz);
		if (id != null) {
			return id;
		}
		String tranCode = getTranCode(clazz);
		if (StringUtils.isBlank(tranCode)) {
			return null;
		}
		id = Integer.parseInt(tranCode, 16);
		class2Id.put(clazz, id);
		id2Class.put(id, clazz);
		return id;
	}

	private String getTranCode(Class<?> clazz) {
		String name = clazz.getName();
		if (name.endsWith("Request")) {
			return StringUtils.substringBetween(clazz.getName(), "Terminal0x", "Request");
		} else if (name.endsWith("Response")) {
			return StringUtils.substringBetween(clazz.getName(), "Terminal0x", "Response");
		}
		return null;
	}

	public static void main(String[] args) {
		System.out.println(Integer.parseInt("271F", 16));
	}
}
